const BaseHardware = require("./baseHardware.js")
const { exec } = require('child_process');
const os = require('os');
const { logger } = require("ee-core/log");
class WinHardwareService extends BaseHardware {
    async getCPUId() {
        return new Promise((resolve, reject) => {
            exec('C:\\Windows\\System32\\wbem\\wmic.exe cpu get ProcessorId', (error, stdout) => {
                if (error) return reject(error);
                const lines = stdout.trim().split('\n');
                resolve(lines.length > 1 ? lines[1].trim() : 'Unknown');
            });
        });
    }
    async getDiskSerialNumber() {
        return new Promise((resolve, reject) => {
            exec('C:\\Windows\\System32\\wbem\\wmic.exe diskdrive get serialnumber', (error, stdout) => {
                if (error) return reject(error);
                const lines = stdout.trim().split('\n');
                let result = lines.length > 1 ? lines[1].trim() : 'Unknown'
                result = result.replace(/\s+/g, '').replace(/\.$/, '');
                resolve(result);
            });
        });
    }

    async _getGatewayAddress() {
        return new Promise((resolve, reject) => {
            exec('route print', (error, stdout) => {
                if (error) return reject(error);
                const lines = stdout.split('\n');
                const gatewayLine = lines.find(line =>
                    line.includes('0.0.0.0') &&
                    line.includes('0.0.0.0') &&
                    !line.includes('On-link')
                );

                if (gatewayLine) {
                    const parts = gatewayLine.trim().split(/\s+/);
                    resolve(parts[2] || 'Unknown');
                } else {
                    resolve('Unknown');
                }
            });
        });
    }
    async _getGatewayMacAddress(gateway) {
        try {
            if (!gateway) {
                gateway = await this._getGatewayAddress();
            }

            if (gateway === 'Unknown') {
                return 'Unknown';
            }

            return new Promise((resolve, reject) => {
                exec('C:\\Windows\\System32\\arp -a', (error, stdout) => {
                    if (error) return reject(error);
                    const lines = stdout.split('\n');
                    const gatewayLine = lines.find(line =>
                        line.includes(gateway+" ") &&
                        !line.includes('incomplete')
                    );

                    if (gatewayLine) {
                        const parts = gatewayLine.trim().split(/\s+/);
                        resolve(parts[1] || 'Unknown');
                    } else {
                        resolve('Unknown');
                    }
                });
            });
        } catch (error) {
            return 'Unknown';
        }
    }
    // 获取网关集（interface IP => gateway IP）
    async _getGatewayMap() {
        return new Promise((resolve, reject) => {
            exec("C:\\Windows\\System32\\route print", (error, stdout) => {
                if (error) return reject(`获取路由表失败: ${error.message}`);

                const lines = stdout
                    .split("\n")
                    .filter(
                        (line) =>
                            /^\s*0\.0\.0\.0\s+0\.0\.0\.0/.test(line) &&
                            !line.includes("On-link")
                    );

                const gatewayMap = {};
                lines.forEach((line) => {
                    const parts = line.trim().split(/\s+/);
                    if (parts.length >= 4) {
                        const interfaceIp = parts[3];
                        const gatewayIp = parts[2];
                        if (interfaceIp && gatewayIp) {
                            gatewayMap[interfaceIp] = gatewayIp;
                        }
                    }
                });

                resolve(gatewayMap);
            });
        });
    }

    // 获取 MAC 地址和描述信息
    _getMacAddressAndDescriptionMap() {
        return new Promise((resolve, reject) => {
            exec("C:\\Windows\\System32\\route print", (error, stdout) => {
                if (error) return reject(`获取路由表失败: ${error.message}`);
                const lines = stdout.split("\n");
                // 转换为 MAC:Description 的 Map 结构
                const macDescMap = lines.reduce((acc, line) => {
                    const match = /^(\d+)\.\.\.([0-9a-fA-F ]{17})\s+\.+([\s\S]*)$/.exec(line.trim());
                    if (match) {
                        const [, , mac, description] = match;
                        const formattedMac = mac.trim().replace(/ /g, ":");
                        acc[formattedMac] = description.trim();
                    }
                    return acc;
                }, {});
                resolve(macDescMap);
            });
        });
    }

    async getNetworkDetails() {
        const interfaces = os.networkInterfaces();
        const infoList = [];
        // 获取网关（IP -> 网关）
        const gatewayMap = await this._getGatewayMap().catch((err) => {
            logger.error("获取网关映射失败:", err.message);
            return {};
        });

        // 获取mac地址和描述（mac -> description）
        const macAddressAndDescriptionMap = await this._getMacAddressAndDescriptionMap().catch((err) => {
            logger.error("获取mac地址和描述失败:", err.message);
            return {};
        });

        const gatewayIps = [...new Set(Object.values(gatewayMap))];

        // 获取网关 MAC 地址
        const gatewayMacMap = {};
        for (const gw of gatewayIps) {
            try {
                const mac = await this._getGatewayMacAddress(gw);
                if (mac) gatewayMacMap[gw] = mac;
            } catch (error) {
                logger.warn(`获取网关 ${gw} 的 MAC 地址失败:`, error.message);
            }
        }

        // 收集符合条件的网络接口信息
        for (const ifname in interfaces) {
            for (const iface of interfaces[ifname]) {
                if (
                    !iface.internal &&
                    iface.mac !== "00:00:00:00:00:00" &&
                    iface.family === "IPv4"
                ) {
                    const gatewayIp = gatewayMap[iface.address] || "Unknown";
                    const gatewayMac = gatewayMacMap[gatewayIp] || "Unknown";
                    const description = macAddressAndDescriptionMap[iface.mac] || "Unknown";
                    if (gatewayMac != "Unknown") { //找不到的不要
                        infoList.push({
                            ip: iface.address,
                            interface: ifname,
                            mac: iface.mac,
                            gateway: gatewayIp,
                            gatewayMac: gatewayMac,
                            description: description,
                        });
                    }

                }
            }
        }

        return infoList;
    }
    async _getRegistrySubKeys(path) {
        return new Promise((resolve, reject) => {
            const command = `reg query "${path}"`;
            exec(command, (error, stdout, stderr) => {
                if (error) {
                    return reject(stderr || error.message);
                }

                // 1. 分割输出为行数组
                const lines = stdout
                    .split('\n')
                    .map(line => line.trim())
                    .filter(line => line.includes(path));

                // 2. 提取子键名称
                const subKeys = lines
                    .map(line => {
                        const parts = line.split('\\');
                        return parts[parts.length - 1];
                    })
                    .filter(key => key && !key.includes('HKEY_')); // 排除无效键和根键

                resolve(subKeys);
            });
        });
    }
    //读取注册表信息
    async _readRegistryStructure(path) {
        try {
            // Step 1: 获取主键下的所有子键名称
            const subKeys = await this._getRegistrySubKeys(path);

            // Step 2: 遍历每个子键，获取其 ServiceName 和 Description
            const result = [];


            for (const subKey of subKeys) {
                const subPath = `${path}\\${subKey}`;
                const values = await this._getRegistryValues(subPath);

                result.push({
                    name: subKey,
                    ServiceName: values.ServiceName,
                    Description: values.Description
                });
            }

            return result;
        } catch (err) {
            logger.error(`读取失败: ${path}`, err.message);
            return [];
        }
    }

    async _getRegistryValues(subPath) {
        return new Promise((resolve, reject) => {
            const command = `reg query "${subPath}"`;
            exec(command, (error, stdout, stderr) => {
            if (error) {
                return reject(stderr || error.message);
            }
            const values = {
                ServiceName: null,
                Description: null
            };

            const lines = stdout.split('\n');
            for (const line of lines) {
                const trimmed = line.trim();
                if (trimmed.includes('ServiceName')) {
                values.ServiceName = trimmed.split(/\s{2,}/)[2];
                } else if (trimmed.includes('Description')) {
                values.Description = trimmed.split(/\s{2,}/)[2];
                }
            }

            resolve(values);
            });
        });
    }



    async networkCardDrive() {
        const regPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards"
        const regNetworkCards = await this._readRegistryStructure(regPath);
        return regNetworkCards;
    }
}

module.exports = {
    WinHardwareService,
    winHardwareService: new WinHardwareService()
};

